package com.windy.service;

import com.windy.app.vo.InfoVO;
import com.windy.app.vo.Result;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@ServerEndpoint("/chat/{userId}")
public class WebSocketService {

    /**
     * 在线人数
     */
    private static volatile AtomicInteger currentOnlineNumber = new AtomicInteger(0);

    /**
     * 以userId为key，WebSocketService为value，将每个客户端对应的WebSocketService保存起来
     */
    private static ConcurrentHashMap<String, WebSocketService> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 会话
     */
    private Session session;

    /**
     * 接收的userId
     */
    private String userId = "";

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session){
        this.session = session;
        this.userId = userId;
        //判断用户是否在线，如果已经在线，将其覆盖（也可以强行在其他地方下线）
        if (webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            webSocketMap.put(userId,this);
        }else {
            webSocketMap.put(userId,this);
            addOnlineNumber();
        }
        System.out.println("用户"+userId+"连接成功！当前在线人数："+getOnlineNumber());
    }

    @OnClose
    public void onClose(){
        //判断用户是否在线，在线就处理下线操作，在webSocketMap中删除记录
        if (webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            subOnlineNumber();
        }
        System.out.println("用户"+userId+"下线！当前在线人数："+getOnlineNumber());
    }

    @OnMessage
    public void onMessage(String message,Session session) throws IOException {
        System.out.println("用户消息:" + userId + ",报文:" + message);
        //消息可以保存在redis中
        if (StringUtils.isNotBlank(message)){
            InfoVO infoVO = (InfoVO) JSONObject.toBean(JSONObject.fromObject(message), InfoVO.class);
            System.out.println(infoVO);
            if (StringUtils.isNotBlank(infoVO.getToUserId()) && webSocketMap.containsKey(userId)){
                webSocketMap.get(infoVO.getToUserId()).sendMessageToUserId(infoVO.getMessage(),infoVO.getToUserId());
            }else {
                System.out.println("用户" +infoVO.getToUserId()+"不在线！");
            }
        }
    }

    @OnError
    public void onError(Session session,Throwable error){
        System.out.println("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    public Result<String> sendMessageToUserId(String message, String toUserId) throws IOException {
        if (webSocketMap.containsKey(toUserId)){
            webSocketMap.get(toUserId).session.getBasicRemote().sendText(message);
            return new Result<String>(true,"消息发送成功，当前在线人数"+getOnlineNumber());
        }else {
            return new Result<String>(false,"消息发送失败,当前用户不在线");
        }
    }

    public Result<String> sendMessageToAll(String message) throws IOException {
        for (WebSocketService webSocketService:webSocketMap.values()){
            webSocketService.session.getBasicRemote().sendText(message);
        }
        return new Result<String>(true,"消息发送成功，当前在线人数"+getOnlineNumber());
    }


    public static synchronized int getOnlineNumber(){
        return currentOnlineNumber.get();
    }
    public static synchronized void addOnlineNumber(){
        WebSocketService.currentOnlineNumber.incrementAndGet();
    }
    public static synchronized void subOnlineNumber(){
        WebSocketService.currentOnlineNumber.decrementAndGet();
    }
}
